package com.cm.res.scanner;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ScannerTaskManager {

    private static final String LOG_TAG = "ScannerTaskManager";

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int MAXIMUM_POOL_SIZE = CORE_POOL_SIZE * 2;
    private static final int KEEP_ALIVE_SECONDS = 30;
    private static final AtomicInteger mTasCounter = new AtomicInteger(0);


    private static final ThreadFactory sThreadFactory = new ThreadFactory() {
        private final AtomicInteger mCount = new AtomicInteger(1);

        public Thread newThread(Runnable r) {
            return new Thread(r, "ScannerTaskManager #" + mCount.getAndIncrement());
        }
    };

    private static final BlockingQueue<Runnable> sPoolWorkQueue =
            new LinkedBlockingQueue<Runnable>(Integer.MAX_VALUE);

    private static ThreadPoolExecutor THREAD_POOL_EXECUTOR;
    private static ScannerTaskManager shareInstance;

    static {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
                sPoolWorkQueue, sThreadFactory, new RejectedExecutionHandler() {
            @Override
            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                System.out.println(" ----- ");
            }
        });
        threadPoolExecutor.allowCoreThreadTimeOut(true);
        THREAD_POOL_EXECUTOR = threadPoolExecutor;

        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
            @Override
            public void run() {
                if (sPoolWorkQueue != null) {
                    sPoolWorkQueue.clear();
                }
                if (THREAD_POOL_EXECUTOR == null) return;
                if (!THREAD_POOL_EXECUTOR.isShutdown()) {
                    THREAD_POOL_EXECUTOR.shutdown();
                }
            }
        }));
    }

    public static ScannerTaskManager getInstance() {
        if (shareInstance == null) {
            synchronized (ScannerTaskManager.class) {
                if (shareInstance == null) {
                    shareInstance = new ScannerTaskManager();
                }
            }
        }
        return shareInstance;
    }

    public void commitTask(ScannerTask scannerTask) {
        mTasCounter.incrementAndGet();
        THREAD_POOL_EXECUTOR.execute(scannerTask);
    }


    public boolean isFinish() {
        long completedTaskCount = THREAD_POOL_EXECUTOR.getCompletedTaskCount() + 1;
        return completedTaskCount == mTasCounter.get();
    }

    public void stopTask() {

        if (!THREAD_POOL_EXECUTOR.isShutdown()) {
            THREAD_POOL_EXECUTOR.shutdown();
        }

    }
}
